#ifndef _SERVERTYPE_H_INCLUDED_
#define _SERVERTYPE_H_INCLUDED_

#include "socketlibtypes.h"
#include "list.h"
#include "stack.h"
#include "array.h"
#include "rwlist.h"

#ifdef  __cplusplus
extern "C" {
#endif

struct server_s;

typedef void (*model_handler_pt)(struct server_s*);

enum ESOCKET_STATUS
{
    SOCKET_FREE,
    SOCKET_CONNECTED,
};

enum ERECV_RESULT
{
    RECV_BUFFERSMALL = 0x1,
    RECV_CLOSE = 0x2,
    RECV_OK = 0x4,
    RECV_EAGIN = 0x8,
};

enum ESEND_RESULT
{
    SEND_CLOSE = 0x01,
    SEND_OK = 0x02,
    SEND_EAGIN = 0x04,
};

struct buffer_s
{
    char*   data;
    int data_len;

    int write_pos;
    int read_pos;
};

struct session_s
{
    int index;
    sock fd;
    bool readable;
    bool writable;
    enum ESOCKET_STATUS status;
    struct buffer_s*    send_buffer;
    struct buffer_s*    recv_buffer;
    struct mutex_s*  send_mutex;
    void*   ext_data;
};

#include "server_logic_pt.h"

typedef bool (*server_recv_pt)(struct server_s*, struct session_s* session);
typedef bool (*server_send_pt)(struct server_s*, struct session_s* session);

struct server_s
{
    struct rwlist_s* wait_close_list;
    struct rwlist_s* accepted_list;

    struct list_s* readable_list;
    struct list_s* writable_list;

    int socket_num;
    struct array_s* sockets;
    struct stack_s* free_sockets;

    void (*poll)(struct server_s*);
    void (*handler_io)(struct server_s*);
    server_recv_pt  recv;
    server_send_pt send;
    void (*close)(struct server_s*, struct session_s* session);
    void (*enter)(struct server_s*, struct session_s* session);

    void (*socket_on_logic_send)(struct server_s*, struct session_s* session);

    logic_on_enter_pt logic_on_enter;
    logic_on_close_pt logic_on_close;
    logic_on_recved_pt logic_on_recved;
    void*   ext;
};

bool server_construction(struct server_s* self, int num, int recv_buffer_size, int send_buffer_size);
void server_destroy(struct server_s* self);
void server_enable_session_readable(struct server_s* self, struct session_s* session);
void server_enable_session_writable(struct server_s* self, struct session_s* session);
void server_disable_session_readable(struct server_s* self, struct session_s* session);
void server_disable_session_writable(struct server_s* self, struct session_s* session);

void server_remove_readable(struct server_s* self, struct session_s* session);
void server_remove_writable(struct server_s* self, struct session_s* session);

int session_recv(struct session_s* self);
int session_send(struct session_s* self);

void buffer_adjustto_head(struct buffer_s* self);

void server_handler_recv(struct server_s* self);
void server_handler_send(struct server_s* self);

void session_close(struct session_s* self);
void server_socket_onclose(struct server_s* self, struct session_s* session);

#ifdef  __cplusplus
}
#endif

#endif
